package ui;

import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

import service.OptionsService;
import service.OptionsServiceImpl;
import ui.components.InputTextBox;
import ui.components.JSliderLabel;
import core.NewOption;
import core.NewOptions;

public class ProjectMenuBar<P extends Project> extends MenuBar {

	// Constants
	private static final String PARAM_MENU_NAME = "Paramètres";
	private static final String FILE_MENU_NAME = "Fichier";
	private static final String SUB_MENU_LOAD_NAME = "Charger";
	private static final String EXIT_ITEM_NAME = "Quitter";

	private static final String SUPERFORMULA = "Super Formula...";
	private static final String ELLIPSOID = "Ellipsoide...";
	private static final String KEPLER_OVOID = "Ovoide de Kepler...";
	private static final String PLANETS_ORBITS = "Orbites de planetes...";
	private static final String SPHERE = "Sphere...";
	private static final String PLANETS = "Planètes...";

	private static final long serialVersionUID = 1L;

	// Fields
	private P project;
	/** Menus de la bar */
	private final List<MenuItem> menus = new ArrayList<MenuItem>();
	/** service des options */
	private final OptionsService optionsService;
	/** Options */
	private NewOptions options;
	/** Panel des options */
	private JFrame optionsPanel;
	private final JPanel booleanOptionsPanel = new JPanel();
	private final JPanel valueOptionsPanel = new JPanel();
	private final JPanel otherOptionsPanel = new JPanel();

	// Constructor
	public ProjectMenuBar(final P project) {

		this.project = project;
		this.optionsService = new OptionsServiceImpl();
		this.optionsPanel = createPanelOptions(project);

		// Menu Fichier
		Menu menu = new Menu(FILE_MENU_NAME);
		Menu chargerMenu = new Menu(SUB_MENU_LOAD_NAME);
		menu.add(chargerMenu);

		addMenuItem(chargerMenu, SPHERE, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showNothing();
				project.getProjectOptions().setShowSphere(true);
			}
		});
		addMenuItem(chargerMenu, PLANETS_ORBITS, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showNothing();
				project.getProjectOptions().setShowOrbitalPlanets(true);
			}
		});
		addMenuItem(chargerMenu, KEPLER_OVOID, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showNothing();
				project.getProjectOptions().setShowKeplerOvoid(true);
			}
		});
		addMenuItem(chargerMenu, ELLIPSOID, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showNothing();
				project.getProjectOptions().setShowEllipsoid(true);
			}
		});
		addMenuItem(chargerMenu, SUPERFORMULA, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showNothing();
				project.getProjectOptions().setShowSuperFormula(true);
			}
		});
		addMenuItem(chargerMenu, PLANETS, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showNothing();
				project.getProjectOptions().setShowPlanets(true);
			}
		});
		menus.add(menu);

		// Menu paramètres
		Menu menuParams = new Menu(PARAM_MENU_NAME);
		addMenuItem(menuParams, "Options", new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				showPanelOptions();
			}
		});
		menus.add(menuParams);

		// Quitter
		menu.addSeparator();
		addMenuItem(menu, EXIT_ITEM_NAME, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				project.exit();
			}
		});

		this.add(menu);
		this.add(menuParams);
	}

	private void addMenuItem(Menu menu, String title, ActionListener action) {
		MenuItem item = new MenuItem(title);
		item.addActionListener(action);
		menu.add(item);
	}

	private void showNothing() {
		project.getProjectOptions().showNothing();
	}

	private void showPanelOptions() {
		optionsPanel.setVisible(true);
	}

	/**
	 * TODO Refactorer => simplifier
	 * 
	 * @param project
	 * @return
	 */
	private JFrame createPanelOptions(final P project) {

		// On charge les options
		options = optionsService.load();

		optionsPanel = new JFrame("Options");
		optionsPanel.setSize(400, 400);
		optionsPanel.setLocation(800, 0);
		optionsPanel.setLayout(new FlowLayout());

		LayoutManager layout = new GridLayout(3, 2);
		booleanOptionsPanel.setLayout(layout);
		booleanOptionsPanel.setPreferredSize(new Dimension(optionsPanel.getWidth() - 30, 100));
		booleanOptionsPanel.setBorder(BorderFactory.createTitledBorder("Paramètres"));

		valueOptionsPanel.setLayout(new FlowLayout());
		valueOptionsPanel.setPreferredSize(new Dimension(optionsPanel.getWidth() - 30, 100));
		valueOptionsPanel.setBorder(BorderFactory.createTitledBorder("Valeurs"));

		otherOptionsPanel.setLayout(new FlowLayout());
		otherOptionsPanel.setPreferredSize(new Dimension(optionsPanel.getWidth() - 30, optionsPanel.getHeight()
				- valueOptionsPanel.getHeight() - booleanOptionsPanel.getHeight() - 300));
		otherOptionsPanel.setBorder(BorderFactory.createTitledBorder("Autres"));

		for (NewOption element : options.getOptions()) {
			if (element.getType() == Boolean.TYPE) {
				Checkbox checkbox = new Checkbox(element.getLabel(), Boolean.valueOf("" + element.getValue()));
				checkbox.setPreferredSize(new Dimension(50, 10));
				checkbox.setLocation(10, 10);
				booleanOptionsPanel.add(checkbox);
			}
			if (element.getType() == Integer.TYPE) {
				InputTextBox textBox = new InputTextBox(element.getLabel(), Integer.valueOf("" + element.getValue()));
				valueOptionsPanel.add(textBox);
			}
		}
		JSliderLabel slider = new JSliderLabel("Libellé");
		otherOptionsPanel.add(slider);

		optionsPanel.add(booleanOptionsPanel);
		optionsPanel.add(valueOptionsPanel);
		optionsPanel.add(otherOptionsPanel);

		Button saveButton = new Button("Sauvegarder");
		saveButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				for (Component component : booleanOptionsPanel.getComponents()) {
					if (component instanceof Checkbox) {
						Checkbox checkbox = (Checkbox) component;
						options.getOption(checkbox.getLabel()).setValue(checkbox.getState());
					}
				}
				optionsService.save(options);
				optionsPanel.dispose();
			}
		});

		optionsPanel.add(saveButton);

		Button cancelButton = new Button("Annuler");
		cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				optionsPanel.dispose();
			}
		});

		optionsPanel.add(cancelButton);
		optionsPanel.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				optionsPanel.dispose();
			}
		});
		optionsPanel.setVisible(false);
		return optionsPanel;
	}

	// Accessors
	public void setProject(P project) {
		this.project = project;
	}

	public P getProject() {
		return project;
	}

}
